Passed
Pull Request — develop (#758)
by Kevin Van
08:39 queued 04:54
created

Search   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 197
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 12
eloc 157
dl 0
loc 197
rs 10
c 0
b 0
f 0

9 Functions

Rating   Name   Duplication   Size   Complexity  
A renderQueryResultsCaption 0 13 1
A renderQueryResultItem 0 9 1
A renderForm 0 18 1
A rebuildIndex 0 28 1
A render 0 26 4
A componentDidMount 0 42 1
A handleSubmit 0 2 1
A renderQueryResults 0 19 1
A searchData 0 5 1
1
import Axios from "axios"
2
import { Link } from "gatsby"
3
import * as JsSearch from "js-search"
4
import React, { Component } from "react"
5
6
import "./search-container.scss"
7
8
class Search extends Component {
9
  state = {
10
    articleList: [],
11
    teamList: [],
12
    playerList: [],
13
    staffList: [],
14
    eventList: [],
15
    search: [],
16
    searchResults: [],
17
    isLoading: true,
18
    isError: false,
19
    searchQuery: ``,
20
  }
21
  /**
22
   * React lifecycle method to fetch the data
23
   */
24
  async componentDidMount() {
25
    Axios.get(`https://api.kcvvelewijt.be/jsonapi/node/article?sort=-created`)
26
      .then((result) => {
27
        const articleData = result.data.data
28
        this.setState({ articleList: articleData })
29
30
        return Axios.get(`https://api.kcvvelewijt.be/jsonapi/node/team?sort=title`)
31
      })
32
      .then((result) => {
33
        const teamData = result.data.data
34
        this.setState({ teamList: teamData })
35
36
        return Axios.get(`https://api.kcvvelewijt.be/jsonapi/node/player?sort=title`)
37
      })
38
      .then((result) => {
39
        const playerData = result.data.data
40
        this.setState({ playerList: playerData })
41
42
        return Axios.get(`https://api.kcvvelewijt.be/jsonapi/node/staff?sort=title`)
43
      })
44
      .then((result) => {
45
        const staffData = result.data.data
46
        this.setState({ staffList: staffData })
47
48
        return Axios.get(`https://api.kcvvelewijt.be/jsonapi/node/event?sort=title`)
49
      })
50
      .then((result) => {
51
        const eventData = result.data.data
52
        this.setState({ eventList: eventData })
53
54
        setTimeout(() => {
55
          this.rebuildIndex()
56
        }, 250)
57
      })
58
      .catch((err) => {
59
        this.setState({ isError: true })
60
        console.log(`====================================`)
61
        console.log(`Something bad happened while fetching some data for the search.\n${err}`)
62
        console.log(`====================================`)
63
      })
64
  }
65
  /**
66
   * rebuilds the overall index based on the options
67
   */
68
  rebuildIndex = () => {
69
    const { articleList, teamList, playerList, staffList, eventList } = this.state
70
    const dataToSearch = new JsSearch.Search(`id`)
71
    /**
72
     *  defines a indexing strategy for the data
73
     * more more about it in here https://github.com/bvaughn/js-search#configuring-the-index-strategy
74
     */
75
    dataToSearch.indexStrategy = new JsSearch.PrefixIndexStrategy()
76
    /**
77
     * defines the sanitizer for the search
78
     * to prevent some of the words from being excluded
79
     *
80
     */
81
    dataToSearch.sanitizer = new JsSearch.LowerCaseSanitizer()
82
83
    /**
84
     * defines the search index
85
     * read more in here https://github.com/bvaughn/js-search#configuring-the-search-index
86
     */
87
    dataToSearch.searchIndex = new JsSearch.TfIdfSearchIndex(`id`)
88
    dataToSearch.addIndex([`attributes`, `body`, `processed`])
89
    dataToSearch.addIndex([`attributes`, `title`])
90
    dataToSearch.addDocuments(articleList)
91
    dataToSearch.addDocuments(teamList)
92
    dataToSearch.addDocuments(playerList)
93
    dataToSearch.addDocuments(staffList)
94
    dataToSearch.addDocuments(eventList)
95
    this.setState({ search: dataToSearch, isLoading: false })
96
  }
97
  /**
98
   * handles the input change and perform a search with js-search
99
   * in which the results will be added to the state
100
   */
101
  searchData = (e) => {
102
    const { search } = this.state
103
    const queryResult = search.search(e.target.value)
104
105
    this.setState({ searchQuery: e.target.value, searchResults: queryResult })
106
  }
107
108
  handleSubmit = (e) => {
109
    e.preventDefault()
110
  }
111
112
  renderForm = (searchQuery) => (
113
    <form onSubmit={this.handleSubmit}>
114
      <div>
115
        <label className={`search_input__label`} htmlFor="search">
116
          <input
117
            id="search"
118
            onChange={this.searchData}
119
            className={`search_input__input`}
120
            placeholder="Spelersnaam, ploegnaam, deel van een artikel..."
121
            value={searchQuery}
122
            required
123
          />
124
          <span className={`search_input__label__inner_wrapper`}>
125
            <span className={`search_input__label__inner_text`}>Waar bent u naar op zoek?</span>
126
          </span>
127
        </label>
128
      </div>
129
    </form>
130
  )
131
132
  renderQueryResultsCaption = () => (
133
    <caption>
134
      <i className={`article__footer_related__icon article__footer_related__icon--node--article fa`} /> Nieuwsbericht
135
      <br />
136
      <i className={`article__footer_related__icon article__footer_related__icon--node--team fa`} /> Ploeg
137
      <br />
138
      <i className={`article__footer_related__icon article__footer_related__icon--node--player fa`} /> Speler
139
      <br />
140
      <i className={`article__footer_related__icon article__footer_related__icon--node--staff fa`} /> Staflid
141
      <br />
142
      <i className={`article__footer_related__icon article__footer_related__icon--node--event fa`} /> Evenement
143
      <br />
144
    </caption>
145
  )
146
147
  renderQueryResultItem = (item) => (
148
    <tr key={`row_${item.attributes.drupal_internal__nid}`}>
149
      <td>
150
        <Link to={item.attributes.path.alias}>
151
          <i className={`article__footer_related__icon article__footer_related__icon--${item.type} fa`} />
152
          {item.attributes.title}
153
        </Link>
154
      </td>
155
    </tr>
156
  )
157
158
  renderQueryResults = (queryResults) => (
159
    <div>
160
      <h3>Gevonden resultaten: {queryResults.length}</h3>
161
      <table>
162
        <thead>
163
          <tr>
164
            <th>Titel</th>
165
          </tr>
166
        </thead>
167
        <tbody>
168
          {/* eslint-disable */}
169
          {queryResults.map((item) => {
170
            return this.renderQueryResultItem(item)
171
          })}
172
          {/* eslint-enable */}
173
        </tbody>
174
        {this.renderQueryResultsCaption()}
175
      </table>
176
    </div>
177
  )
178
179
  render() {
180
    const { isError, isLoading, searchResults, searchQuery } = this.state
181
    const queryResults = searchQuery === `` ? [] : searchResults
182
183
    if (isLoading) {
184
      return <p>Zoekfunctie is aan het laden...</p>
185
    }
186
    if (isError) {
187
      return (
188
        <>
189
          <h2>Aiiii...</h2>
190
          <h3>
191
            Er ging iets mis - gelieve <a href="mailto:[email protected]">contact op te nemen</a> indien het
192
            probleem zich blijft voordoen.
193
          </h3>
194
        </>
195
      )
196
    }
197
198
    return (
199
      <div className={`search--placeholder`}>
200
        {this.renderForm(searchQuery)}
201
202
        {queryResults.length > 0 && this.renderQueryResults(queryResults)}
203
      </div>
204
    )
205
  }
206
}
207
export default Search
208